<?php
declare(strict_types=1);

namespace App\Controller;

use App\Repository\PostRepository;
use JsonException;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\DataResponse\DataResponseFactoryInterface;
use Yiisoft\Http\Status;

final class PostController
{
    public function __construct(
        private DataResponseFactoryInterface $responseFactory,
        private PostRepository $posts,
    ) {}

    public function index(): ResponseInterface
    {
        return $this->responseFactory->createResponse($this->posts->all());
    }

    public function show(ServerRequestInterface $request, string $id): ResponseInterface
    {
        $post = $this->posts->findById((int) $id);

        if ($post === null) {
            return $this->responseFactory->createResponse([
                'error' => 'Post not found.',
            ])->withStatus(Status::NOT_FOUND);
        }

        return $this->responseFactory->createResponse($post);
    }

    public function store(ServerRequestInterface $request): ResponseInterface
    {
        try {
            $payload = json_decode((string) $request->getBody(), true, 512, JSON_THROW_ON_ERROR);
        } catch (JsonException $exception) {
            return $this->responseFactory->createResponse([
                'error' => 'Invalid JSON payload.',
            ])->withStatus(Status::BAD_REQUEST);
        }

        if (!is_array($payload)) {
            return $this->responseFactory->createResponse([
                'error' => 'Request body must be a JSON object.',
            ])->withStatus(Status::UNPROCESSABLE_ENTITY);
        }

        $title = isset($payload['title']) && is_string($payload['title']) ? trim($payload['title']) : '';
        $body = isset($payload['body']) && is_string($payload['body']) ? trim($payload['body']) : '';

        $errors = [];
        if ($title === '') {
            $errors['title'][] = 'Title is required.';
        }
        if ($body === '') {
            $errors['body'][] = 'Body is required.';
        }

        if ($errors !== []) {
            return $this->responseFactory->createResponse([
                'errors' => $errors,
            ])->withStatus(Status::UNPROCESSABLE_ENTITY);
        }

        $post = $this->posts->create($title, $body);

        $response = $this->responseFactory
            ->createResponse($post)
            ->withStatus(Status::CREATED);

        if (isset($post['id'])) {
            $response = $response->withHeader('Location', '/api/v1/posts/' . $post['id']);
        }

        return $response;
    }
}
